﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.ComponentModel;
using System.Security.Cryptography;

namespace LargeCMS
{
    partial class Win32
    {
        #region "CONSTS"

        //#define X509_ASN_ENCODING           0x00000001
        internal const int X509_ASN_ENCODING = 0x00000001;

        //#define PKCS_7_ASN_ENCODING         0x00010000
        internal const int PKCS_7_ASN_ENCODING = 0x00010000;

        //#define CMSG_SIGNED                  2
        internal const int CMSG_SIGNED = 2;

        //#define CMSG_ENVELOPED               3
        internal const int CMSG_ENVELOPED = 3;

        //#define CMSG_DETACHED_FLAG                  0x00000004
        internal const int CMSG_DETACHED_FLAG = 0x00000004;

        //#define CMSG_AUTHENTICATED_ATTRIBUTES_FLAG  0x00000008
        internal const int CMSG_AUTHENTICATED_ATTRIBUTES_FLAG = 0x00000008;

        //#define CMSG_ENVELOPE_ALGORITHM_PARAM                15
        internal const int CMSG_ENVELOPE_ALGORITHM_PARAM = 15;

        //#define AT_KEYEXCHANGE		1
        internal const int AT_KEYEXCHANGE = 1;

        //#define AT_SIGNATURE		2
        internal const int AT_SIGNATURE = 2;

        //#define szOID_OIWSEC_rsaSign    "1.3.14.3.2.11"
        internal const String szOID_OIWSEC_rsaSign = "1.3.14.3.2.11";

        //#define szOID_OIWSEC_shaRSA     "1.3.14.3.2.15"
        internal const String szOID_OIWSEC_shaRSA = "1.3.14.3.2.15";

        //#define szOID_OIWSEC_sha        "1.3.14.3.2.18"
        internal const String szOID_OIWSEC_sha = "1.3.14.3.2.18";

        //#define szOID_OIWSEC_sha1       "1.3.14.3.2.26"
        internal const String szOID_OIWSEC_sha1 = "1.3.14.3.2.26";

        //#define szOID_OIWSEC_sha1RSASign "1.3.14.3.2.29"
        internal const String szOID_OIWSEC_sha1RSASign = "1.3.14.3.2.29";

        //#define szOID_RSA_RC4           "1.2.840.113549.3.4"
        internal const String szOID_RSA_RC4 = "1.2.840.113549.3.4";

        //#define szOID_RSA_DES_EDE3_CBC  "1.2.840.113549.3.7"
        internal const String szOID_RSA_DES_EDE3_CBC = "1.2.840.113549.3.7";

        //#define szOID_RSA_signingTime   "1.2.840.113549.1.9.5"
        internal const String szOID_RSA_signingTime = "1.2.840.113549.1.9.5";

        //#define X509_NAME                           ((LPCSTR) 7)
        internal const int X509_NAME = 7;

        //#define CMSG_ENCODED_SIGNER                          28
        internal const int CMSG_ENCODED_SIGNER = 8;
        
        //#define CMSG_CTRL_VERIFY_SIGNATURE       1
        internal const int CMSG_CTRL_VERIFY_SIGNATURE = 1;

        //#define CMSG_CTRL_DECRYPT                2
        internal const int CMSG_CTRL_DECRYPT = 2;

        //#define CMSG_CTRL_VERIFY_SIGNATURE_EX    19
        internal const int CMSG_CTRL_VERIFY_SIGNATURE_EX = 19;

        //#define CMSG_CTRL_ADD_SIGNER             6
        internal const int CMSG_CTRL_ADD_SIGNER = 6;
        
        //#define CMSG_CTRL_ADD_CERT               10
        internal const int CMSG_CTRL_ADD_CERT = 10;        

        //#define CMSG_SIGNER_COUNT_PARAM                      5
        internal const int CMSG_SIGNER_COUNT_PARAM = 5;

        //#define CMSG_SIGNER_INFO_PARAM                       6
        internal const int CMSG_SIGNER_INFO_PARAM = 6;

        //#define CMSG_SIGNER_CERT_INFO_PARAM                  7
        internal const int CMSG_SIGNER_CERT_INFO_PARAM = 7;

        //#define CMSG_CERT_COUNT_PARAM                        11
        internal const int CMSG_CERT_COUNT_PARAM = 11;

        //#define CMSG_CERT_PARAM                              12
        internal const int CMSG_CERT_PARAM = 12;
        
        //#define CMSG_RECIPIENT_COUNT_PARAM                   17
        internal const int CMSG_RECIPIENT_COUNT_PARAM = 17;

        //#define CMSG_RECIPIENT_INFO_PARAM                    19
        internal const int CMSG_RECIPIENT_INFO_PARAM = 19;

        //#define CMSG_ENCODED_MESSAGE                         29
        internal const int CMSG_ENCODED_MESSAGE = 29;

        //#define CERT_STORE_PROV_MSG                 ((LPCSTR) 1)
        internal const int CERT_STORE_PROV_MSG = 1;

        //#define CERT_CLOSE_STORE_FORCE_FLAG         0x00000001
        internal const int CERT_CLOSE_STORE_FORCE_FLAG = 1;

        //#define CERT_KEY_PROV_INFO_PROP_ID          2
        internal const int CERT_KEY_PROV_INFO_PROP_ID = 2;

        //#define CMSG_VERIFY_SIGNER_CERT                     2
        internal const int CMSG_VERIFY_SIGNER_CERT = 2;

        //#define CMSG_RC4_NO_SALT_FLAG               0x40000000
        internal const int CMSG_RC4_NO_SALT_FLAG = 0x40000000;

        //#define CERT_STORE_PROV_SYSTEM_W            ((LPCSTR) 10)
        //#define CERT_STORE_PROV_SYSTEM              CERT_STORE_PROV_SYSTEM_W
        internal const int CERT_STORE_PROV_SYSTEM = 10;

        //#define CERT_SYSTEM_STORE_CURRENT_USER_ID       1
        //#define CERT_SYSTEM_STORE_LOCATION_SHIFT        16
        //#define CERT_SYSTEM_STORE_CURRENT_USER          \
        //  (CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT)
        internal const int CERT_SYSTEM_STORE_CURRENT_USER = 1 << 16;
        #endregion

        #region "STRUCTS"

        //typedef struct _CRYPT_ALGORITHM_IDENTIFIER {
        //  LPSTR            pszObjId;
        //  CRYPT_OBJID_BLOB Parameters;
        //} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CRYPT_ALGORITHM_IDENTIFIER
        {
            public string pszObjId;
            public BLOB Parameters;

            public void Dispose()
            {
                Parameters.Dispose();
            }
        }

        //typedef struct _CERT_ID {
        //  DWORD dwIdChoice;
        //  union {
        //    CERT_ISSUER_SERIAL_NUMBER IssuerSerialNumber;
        //    CRYPT_HASH_BLOB KeyId;
        //    CRYPT_HASH_BLOB HashId;
        //  } ;
        //} CERT_ID, *PCERT_ID;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CERT_ID
        {
            public int dwIdChoice;
            public BLOB IssuerSerialNumberOrKeyIdOrHashId;
        }

        //typedef struct _CRYPT_ATTRIBUTE {
        //  LPSTR            pszObjId;
        //  DWORD            cValue;
        //  PCRYPT_ATTR_BLOB rgValue;
        //} CRYPT_ATTRIBUTE, *PCRYPT_ATTRIBUTE;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CRYPT_ATTRIBUTE
        {
            public string pszObjId;
            public int cValue;
            public IntPtr rgValue;

            public void Dispose()
            {
                if (!rgValue.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgValue); }
            }
        }

        //typedef struct _CMSG_SIGNER_ENCODE_INFO {
        //  DWORD                      cbSize;
        //  PCERT_INFO                 pCertInfo;
        //  union {
        //    HCRYPTPROV hCryptProv;
        //    NCRYPT_KEY_HANDLE hNCryptKey;
        //  } ;
        //  DWORD                      dwKeySpec;
        //  CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
        //  void *                     pvHashAuxInfo;
        //  DWORD                      cAuthAttr;
        //  PCRYPT_ATTRIBUTE           rgAuthAttr;
        //  DWORD                      cUnauthAttr;
        //  PCRYPT_ATTRIBUTE           rgUnauthAttr;
        //  CERT_ID                    SignerId;
        //  CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
        //  void *                     pvHashEncryptionAuxInfo;
        //} CMSG_SIGNER_ENCODE_INFO, *PCMSG_SIGNER_ENCODE_INFO;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CMSG_SIGNER_ENCODE_INFO
        {
            public int cbSize;
            public IntPtr pCertInfo;
            public IntPtr hCryptProvOrhNCryptKey;
            public int dwKeySpec;
            public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
            public IntPtr pvHashAuxInfo;
            public int cAuthAttr;
            public IntPtr rgAuthAttr;
            public int cUnauthAttr;
            public IntPtr rgUnauthAttr;
            public CERT_ID                    SignerId;
            public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
            public IntPtr pvHashEncryptionAuxInfo;

            public void Dispose()
            {
                if (!hCryptProvOrhNCryptKey.Equals(IntPtr.Zero)) { Win32.CryptReleaseContext(hCryptProvOrhNCryptKey, 0); } 
                if (!rgAuthAttr.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgAuthAttr); }
                if (!rgUnauthAttr.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgUnauthAttr); }
            }
        }

        //typedef struct _CERT_CONTEXT {
        //  DWORD      dwCertEncodingType;
        //  BYTE *     pbCertEncoded;
        //  DWORD      cbCertEncoded;
        //  PCERT_INFO pCertInfo;
        //  HCERTSTORE hCertStore;
        //} CERT_CONTEXT, *PCERT_CONTEXT;
        //typedef const CERT_CONTEXT *PCCERT_CONTEXT;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CERT_CONTEXT
        {
            public int dwCertEncodingType;
            public IntPtr pbCertEncoded;
            public int cbCertEncoded;
            public IntPtr pCertInfo;
            public IntPtr hCertStore;
        }

        //typedef struct _CRYPTOAPI_BLOB {
        //  DWORD cbData;
        //  BYTE *pbData;
        //} CRYPT_intEGER_BLOB, *PCRYPT_intEGER_BLOB, CRYPT_Uint_BLOB, *PCRYPT_Uint_BLOB, CRYPT_OBJID_BLOB, *PCRYPT_OBJID_BLOB, CERT_NAME_BLOB, CERT_RDN_VALUE_BLOB, *PCERT_NAME_BLOB, *PCERT_RDN_VALUE_BLOB, CERT_BLOB, *PCERT_BLOB, CRL_BLOB, *PCRL_BLOB, DATA_BLOB, *PDATA_BLOB, CRYPT_DATA_BLOB, *PCRYPT_DATA_BLOB, CRYPT_HASH_BLOB, *PCRYPT_HASH_BLOB, CRYPT_DIGEST_BLOB, *PCRYPT_DIGEST_BLOB, CRYPT_DER_BLOB, PCRYPT_DER_BLOB, CRYPT_ATTR_BLOB, *PCRYPT_ATTR_BLOB;
        [StructLayout(LayoutKind.Sequential)]
        internal struct BLOB
        {
            public int cbData;
            public IntPtr pbData;

            public void Dispose()
            {
                if (!pbData.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(pbData); }
            }
        }

        //typedef struct _CRYPT_BIT_BLOB {
        //  DWORD cbData;
        //  BYTE  *pbData;
        //  DWORD cUnusedBits;
        //} CRYPT_BIT_BLOB, *PCRYPT_BIT_BLOB;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CRYPT_BIT_BLOB
        {
            public int cbData;
            public IntPtr pbData;
            public int cUnusedBits;
        }

        //struct CMSG_SIGNED_ENCODE_INFO
        //{
        //    DWORD cbSize;
        //    DWORD cSigners;
        //    PCMSG_SIGNER_ENCODE_INFO rgSigners;
        //    DWORD cCertEncoded;
        //    CERT_BLOB rgCertEncoded;
        //    DWORD cCrlEncoded;
        //    PCRL_BLOB rgCrlEncoded;
        //    DWORD cAttrCertEncoded;
        //    PCERT_BLOB rgAttrCertEncoded;
        //};
        [StructLayout(LayoutKind.Sequential)]
        internal struct CMSG_SIGNED_ENCODE_INFO
        {
            public int cbSize;
            public int cSigners;
            public IntPtr rgSigners;
            public int cCertEncoded;
            public IntPtr rgCertEncoded;
            public int cCrlEncoded;
            public IntPtr rgCrlEncoded;
            public int cAttrCertEncoded;
            public IntPtr rgAttrCertEncoded;

            public void Dispose()
            {
                if (!rgSigners.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgSigners); }
                if (!rgCertEncoded.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgCertEncoded); }
                if (!rgCrlEncoded.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgCrlEncoded); }
                if (!rgAttrCertEncoded.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgAttrCertEncoded); }
            }
        }

        //typedef struct _CRYPT_ATTRIBUTES {
        //  DWORD            cAttr;
        //  PCRYPT_ATTRIBUTE rgAttr;
        //} CRYPT_ATTRIBUTES, *PCRYPT_ATTRIBUTES, CMSG_ATTR;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CRYPT_ATTRIBUTES
        {
            public int cAttr;
            public IntPtr rgAttr;
        }

        //typedef struct _CMSG_SIGNER_INFO {
        //  DWORD                      dwVersion;
        //  CERT_NAME_BLOB             Issuer;
        //  CRYPT_INTEGER_BLOB         SerialNumber;
        //  CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
        //  CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
        //  CRYPT_DATA_BLOB            EncryptedHash;
        //  CRYPT_ATTRIBUTES           AuthAttrs;
        //  CRYPT_ATTRIBUTES           UnauthAttrs;
        //} CMSG_SIGNER_INFO, *PCMSG_SIGNER_INFO;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CMSG_SIGNER_INFO
        {
            public int dwVersion;
            public BLOB Issuer;
            public BLOB SerialNumber;
            public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
            public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
            public BLOB EncryptedHash;
            public CRYPT_ATTRIBUTES           AuthAttrs;
            public CRYPT_ATTRIBUTES           UnauthAttrs;
        }

        //typedef struct _CMSG_STREAM_INFO {
        //  DWORD                  cbContent;
        //  PFN_CMSG_STREAM_OUTPUT pfnStreamOutput;
        //  void *                 pvArg;
        //} CMSG_STREAM_INFO, *PCMSG_STREAM_INFO;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CMSG_STREAM_INFO
        {
            public int cbContent;
            public StreamOutputCallbackDelegate pfnStreamOutput;
            public IntPtr pvArg;
        }

        //typedef struct _CERT_PUBLIC_KEY_INFO {
        //  CRYPT_ALGORITHM_IDENTIFIER Algorithm;
        //  CRYPT_BIT_BLOB             PublicKey;
        //} CERT_PUBLIC_KEY_INFO, *PCERT_PUBLIC_KEY_INFO;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CERT_PUBLIC_KEY_INFO
        {
            public CRYPT_ALGORITHM_IDENTIFIER Algorithm;
            public CRYPT_BIT_BLOB PublicKey;
        }

        //typedef struct _FILETIME {
        //  DWORD dwLowDateTime;
        //  DWORD dwHighDateTime;
        //} FILETIME, *PFILETIME;
        [StructLayout(LayoutKind.Sequential)]
        internal struct FILETIME
        {
            public int dwLowDateTime;
            public int dwHighDateTime;
        }

        //typedef struct _CERT_INFO {
        //  DWORD                      dwVersion;
        //  CRYPT_INTEGER_BLOB         SerialNumber;
        //  CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
        //  CERT_NAME_BLOB             Issuer;
        //  FILETIME                   NotBefore;
        //  FILETIME                   NotAfter;
        //  CERT_NAME_BLOB             Subject;
        //  CERT_PUBLIC_KEY_INFO       SubjectPublicKeyInfo;
        //  CRYPT_BIT_BLOB             IssuerUniqueId;
        //  CRYPT_BIT_BLOB             SubjectUniqueId;
        //  DWORD                      cExtension;
        //  PCERT_EXTENSION            rgExtension;
        //} CERT_INFO, *PCERT_INFO;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CERT_INFO
        {
            public int dwVersion;
            public BLOB SerialNumber;
            public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
            public BLOB Issuer;
            public FILETIME NotBefore;
            public FILETIME NotAfter;
            public BLOB Subject;
            public CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
            public CRYPT_BIT_BLOB IssuerUniqueId;
            public CRYPT_BIT_BLOB SubjectUniqueId;
            public int cExtension;
            public IntPtr rgExtension;
        }
        
        //typedef struct _CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA {
        //  DWORD             cbSize;
        //  HCRYPTPROV_LEGACY hCryptProv;
        //  DWORD             dwSignerIndex;
        //  DWORD             dwSignerType;
        //  void              *pvSigner;
        //} CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA, *PCMSG_CTRL_VERIFY_SIGNATURE_EX_PARA;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA
        {
            public int cbSize;
            public IntPtr hCryptProv;
            public int dwSignerIndex;
            public int dwSignerType;
            public IntPtr pvSigner;
        }

        //typedef struct _CMSG_ENVELOPED_ENCODE_INFO {
        //  DWORD                       cbSize;
        //  HCRYPTPROV_LEGACY           hCryptProv;
        //  CRYPT_ALGORITHM_IDENTIFIER  ContentEncryptionAlgorithm;
        //  void                        *pvEncryptionAuxInfo;
        //  DWORD                       cRecipients;
        //  PCERT_INFO                  *rgpRecipients;
        //  PCMSG_RECIPIENT_ENCODE_INFO rgCmsRecipients;
        //  DWORD                       cCertEncoded;
        //  PCERT_BLOB                  rgCertEncoded;
        //  DWORD                       cCrlEncoded;
        //  PCRL_BLOB                   rgCrlEncoded;
        //  DWORD                       cAttrCertEncoded;
        //  PCERT_BLOB                  rgAttrCertEncoded;
        //  DWORD                       cUnprotectedAttr;
        //  PCRYPT_ATTRIBUTE            rgUnprotectedAttr;
        //} CMSG_ENVELOPED_ENCODE_INFO, *PCMSG_ENVELOPED_ENCODE_INFO;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CMSG_ENVELOPED_ENCODE_INFO
        {
            public int cbSize;
            public IntPtr hCryptProv;
            public CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm;
            public IntPtr pvEncryptionAuxInfo;
            public int cRecipients;
            public IntPtr rgpRecipients;
            public IntPtr rgCmsRecipients;
            public int cCertEncoded;
            public IntPtr rgCertEncoded;
            public int cCrlEncoded;
            public IntPtr rgCrlEncoded;
            public int cAttrCertEncoded;
            public IntPtr rgAttrCertEncoded;
            public int cUnprotectedAttr;
            public IntPtr rgUnprotectedAttr;

            public void Dispose()
            {
                ContentEncryptionAlgorithm.Dispose();
                if (!pvEncryptionAuxInfo.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(pvEncryptionAuxInfo); }
                if (!rgpRecipients.Equals(IntPtr.Zero)) { Marshal.FreeHGlobal(rgpRecipients); }
            }
        }

        //typedef struct _CMSG_RC4_AUX_INFO {
        //  DWORD cbSize;
        //  DWORD dwBitLen;
        //} CMSG_RC4_AUX_INFO, *PCMSG_RC4_AUX_INFO;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CMSG_RC4_AUX_INFO
        {
            public int cbSize;
            public int dwBitLen;
        }

        //typedef struct _CMSG_CTRL_DECRYPT_PARA {
        //  DWORD cbSize;
        //  union {
        //    HCRYPTPROV        hCryptProv;
        //    NCRYPT_KEY_HANDLE hNCryptKey;
        //  } ;
        //  DWORD dwKeySpec;
        //  DWORD dwRecipientIndex;
        //} CMSG_CTRL_DECRYPT_PARA, *PCMSG_CTRL_DECRYPT_PARA;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CMSG_CTRL_DECRYPT_PARA
        {
            public int cbSize;
            public IntPtr hCryptProvOrNCryptKey;
            public int dwKeySpec;
            public int dwRecipientIndex;
        }
        
        //typedef struct _CRYPT_KEY_PROV_INFO {
        //  LPWSTR                pwszContainerName;
        //  LPWSTR                pwszProvName;
        //  DWORD                 dwProvType;
        //  DWORD                 dwFlags;
        //  DWORD                 cProvParam;
        //  PCRYPT_KEY_PROV_PARAM rgProvParam;
        //  DWORD                 dwKeySpec;
        //} CRYPT_KEY_PROV_INFO, *PCRYPT_KEY_PROV_INFO;
        [StructLayout(LayoutKind.Sequential)]
        internal struct CRYPT_KEY_PROV_INFO
        {
            [MarshalAs(UnmanagedType.LPWStr)]public string pwszContainerName;
            [MarshalAs(UnmanagedType.LPWStr)]public string pwszProvName;
            public int dwProvType;
            public int dwFlags;
            public int cProvParam;
            public IntPtr rgProvParam;
            public int dwKeySpec;
        }

        #endregion

        #region "DELEGATES"

        internal delegate Boolean StreamOutputCallbackDelegate(IntPtr pvArg, IntPtr pbData, int cbData, Boolean fFinal);

        #endregion

        #region "API"

        //BOOL WINAPI CryptAcquireContext(
        //  __out  HCRYPTPROV *phProv,
        //  __in   LPCTSTR pszContainer,
        //  __in   LPCTSTR pszProvider,
        //  __in   DWORD dwProvType,
        //  __in   DWORD dwFlags
        //);
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern Boolean CryptAcquireContext(
          out SafeCSPHandle hProv,
          string pszContainer,
          string pszProvider,
          int dwProvType,
          int dwFlags
        );

        //BOOL WINAPI CryptEncodeObject(
        //  __in     DWORD dwCertEncodingType,
        //  __in     LPCSTR lpszStructType,
        //  __in     const void *pvStructInfo,
        //  __out    BYTE *pbEncoded,
        //  __inout  DWORD *pcbEncoded
        //);
        [DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        internal static extern bool CryptEncodeObject(
            int dwCertEncodingType,
            string lpszStructType,
            ref long pvStructInfo,
            SafeNTHeapHandle pbEncoded,
            ref int pcbEncoded
        );        

        //BOOL WINAPI CryptDecodeObject(
        //  __in     DWORD dwCertEncodingType,
        //  __in     LPCSTR lpszStructType,
        //  __in     const BYTE *pbEncoded,
        //  __in     DWORD cbEncoded,
        //  __in     DWORD dwFlags,
        //  __out    void *pvStructInfo,
        //  __inout  DWORD *pcbStructInfo
        //);
        [DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        internal static extern Boolean CryptDecodeObject(
            int dwCertEncodingType,
            string lpszStructType,
            IntPtr pbEncoded,
            int cbEncoded,
            int dwFlags,
            out long pvStructInfo,
            ref int pcbStructInfo
        );
        [DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        internal static extern Boolean CryptDecodeObject(
            int dwCertEncodingType,
            int lpszStructType,
            IntPtr pbEncoded,
            int cbEncoded,
            int dwFlags,
            StringBuilder pvStructInfo,
            ref int pcbStructInfo
        );     

        //HCRYPTMSG WINAPI CryptMsgOpenToEncode(
        //  __in      DWORD dwMsgEncodingType,
        //  __in      DWORD dwFlags,
        //  __in      DWORD dwMsgType,
        //  __in      const void *pvMsgEncodeInfo,
        //  __in_opt  LPSTR pszInnerContentObjID,
        //  __in      PCMSG_STREAM_INFO pStreamInfo
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern SafeMsgHandle CryptMsgOpenToEncode(
            int dwMsgEncodingType,
            int dwFlags,
            int dwMsgType,
            ref CMSG_SIGNED_ENCODE_INFO pvMsgEncodeInfo,
            string pszInnerContentObjID,
            ref CMSG_STREAM_INFO pStreamInfo
        );
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern SafeMsgHandle CryptMsgOpenToEncode(
            int dwMsgEncodingType,
            int dwFlags,
            int dwMsgType,
            ref CMSG_ENVELOPED_ENCODE_INFO pvMsgEncodeInfo,
            string pszInnerContentObjID,
            ref CMSG_STREAM_INFO pStreamInfo
        );
        
        //HCRYPTMSG WINAPI CryptMsgOpenToDecode(
        //  __in      DWORD dwMsgEncodingType,
        //  __in      DWORD dwFlags,
        //  __in      DWORD dwMsgType,
        //  __in      HCRYPTPROV_LEGACY hCryptProv,
        //  __in      PCERT_INFO pRecipientInfo,
        //  __in_opt  PCMSG_STREAM_INFO pStreamInfo
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern SafeMsgHandle CryptMsgOpenToDecode(
            int dwMsgEncodingType,
            int dwFlags,
            int dwMsgType,
            IntPtr hCryptProv,
            IntPtr pRecipientInfo,
            ref CMSG_STREAM_INFO pStreamInfo
        );
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern SafeMsgHandle CryptMsgOpenToDecode(
            int dwMsgEncodingType,
            int dwFlags,
            int dwMsgType,
            IntPtr hCryptProv,
            IntPtr pRecipientInfo,
            IntPtr pStreamInfo
        );
        
        //BOOL WINAPI CryptMsgClose(
        //  __in  HCRYPTMSG hCryptMsg
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgClose(
            IntPtr hCryptMsg
        );

        //BOOL WINAPI CryptMsgUpdate(
        //  __in  HCRYPTMSG hCryptMsg,
        //  __in  const BYTE *pbData,
        //  __in  DWORD cbData,
        //  __in  BOOL fFinal
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgUpdate(
            IntPtr hCryptMsg,
            Byte[] pbData,
            int cbData,
            Boolean fFinal
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgUpdate(
            IntPtr hCryptMsg,
            IntPtr pbData,
            int cbData,
            Boolean fFinal
        );

        //BOOL WINAPI CryptMsgGetParam(
        //  __in     HCRYPTMSG hCryptMsg,
        //  __in     DWORD dwParamType,
        //  __in     DWORD dwIndex,
        //  __out    void *pvData,
        //  __inout  DWORD *pcbData
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgGetParam(
            SafeMsgHandle hCryptMsg,
            int dwParamType,
            int dwIndex,
            SafeNTHeapHandle pvData,
            ref int pcbData
        );
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgGetParam(
            SafeMsgHandle hCryptMsg,
            int dwParamType,
            int dwIndex,
            out int pvData,
            ref int pcbData
        );    

        //BOOL WINAPI CryptMsgControl(
        //  __in  HCRYPTMSG hCryptMsg,
        //  __in  DWORD dwFlags,
        //  __in  DWORD dwCtrlType,
        //  __in  const void *pvCtrlPara
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgControl(
            SafeMsgHandle hCryptMsg,
            int dwFlags,
            int dwCtrlType,
            IntPtr pvCtrlPara
        );
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgControl(
            SafeMsgHandle hCryptMsg,
            int dwFlags,
            int dwCtrlType,
            ref CMSG_SIGNER_ENCODE_INFO pvCtrlPara
        );
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgControl(
            SafeMsgHandle hCryptMsg,
            int dwFlags,
            int dwCtrlType,
            ref BLOB pvCtrlPara
        );
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgControl(
            SafeMsgHandle hCryptMsg,
            int dwFlags,
            int dwCtrlType,
            ref CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA pvCtrlPara
        );
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CryptMsgControl(
            SafeMsgHandle hCryptMsg,
            int dwFlags,
            int dwCtrlType,
            ref CMSG_CTRL_DECRYPT_PARA pvCtrlPara
        );

        //BOOL WINAPI CryptReleaseContext(
        //  __in  HCRYPTPROV hProv,
        //  __in  DWORD dwFlags
        //);
        [DllImport("advapi32.dll", SetLastError = true)]
        internal static extern Boolean CryptReleaseContext(
            IntPtr hProv,
            int dwFlags
        );

        //PCCERT_CONTEXT WINAPI CertCreateCertificateContext(
        //  __in  DWORD dwCertEncodingType,
        //  __in  const BYTE *pbCertEncoded,
        //  __in  DWORD cbCertEncoded
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern SafeCertContextHandle CertCreateCertificateContext(
            int dwCertEncodingType,
            SafeNTHeapHandle pbCertEncoded,
            int cbCertEncoded
        );

        //BOOL WINAPI CertFreeCertificateContext(
        //  __in  PCCERT_CONTEXT pCertContext
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern Boolean CertFreeCertificateContext(
            IntPtr pCertContext
        );

        //HCERTSTORE WINAPI CertOpenStore(
        //  __in  LPCSTR lpszStoreProvider,
        //  __in  DWORD dwMsgAndCertEncodingType,
        //  __in  HCRYPTPROV_LEGACY hCryptProv,
        //  __in  DWORD dwFlags,
        //  __in  const void *pvPara
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern SafeStoreHandle CertOpenStore(
            int lpszStoreProvider,
            int dwMsgAndCertEncodingType,
            IntPtr hCryptProv,
            int dwFlags,
            SafeMsgHandle pvPara
        );

        //HCERTSTORE WINAPI CertOpenSystemStore(
        //  __in  HCRYPTPROV_LEGACY hprov,
        //  __in  LPTCSTR szSubsystemProtocol
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern SafeStoreHandle CertOpenSystemStore(
            IntPtr hprov,
            string szSubsystemProtocol
        );

        //PCCERT_CONTEXT WINAPI CertGetSubjectCertificateFromStore(
        //  __in  HCERTSTORE hCertStore,
        //  __in  DWORD dwCertEncodingType,
        //  __in  PCERT_INFO pCertId
        //);        
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern SafeCertContextHandle CertGetSubjectCertificateFromStore(
            SafeStoreHandle hCertStore,
            int dwCertEncodingType,
            SafeNTHeapHandle pCertId
        );

        //BOOL WINAPI CertCloseStore(
        //  __in  HCERTSTORE hCertStore,
        //  __in  DWORD dwFlags
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern IntPtr CertCloseStore(
            IntPtr hCertStore,
            int dwFlags
        );

        //BOOL WINAPI CertGetCertificateContextProperty(
        //  __in     PCCERT_CONTEXT pCertContext,
        //  __in     DWORD dwPropId,
        //  __out    void *pvData,
        //  __inout  DWORD *pcbData
        //);
        [DllImport("Crypt32.dll", SetLastError = true)]
        internal static extern bool CertGetCertificateContextProperty(
            SafeCertContextHandle pCertContext,
            int dwPropId,
            SafeNTHeapHandle pvData,
            ref int pcbData
        );

        // void * memset ( void * ptr, int value, size_t num );
        [DllImport("msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
        internal static extern IntPtr MemSet(
            IntPtr ptr, 
            int value, 
            int num
        );

        #endregion
    }
}
